/**
 * 
 */
package view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.sql.SQLException;

import javax.swing.JPanel;
import javax.swing.SwingWorker;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alee.laf.button.WebButton;
import com.alee.laf.label.WebLabel;
import com.alee.laf.progressbar.WebProgressBar;

import database.CandoDatabase;
import database.CreateCandoTable;
import database.CreateCompoundMappingTable;
import database.PopulateCandoTable;

/**
 * @author Jamada
 */
public class DatabasePanel extends JPanel {
	private static final Logger logger = LoggerFactory.getLogger(DatabasePanel.class);
	
	private static final long serialVersionUID = 801472456426081902L;
	private final CandoDatabase database;
	private WebProgressBar progressBar;
	private WebButton popCompMapTable;
	private WebButton popCandoTable;
	
	public DatabasePanel(final CandoDatabase db) {
		this.database = db;
        this.setLayout(new BorderLayout());
        this.setBackground(Color.WHITE);
        buildPanel();
	}
	
	private void buildPanel() {
        JPanel masterPanel = new JPanel();
        GridLayout grid = new GridLayout(6, 1);;
        grid.setVgap(10);
        masterPanel.setLayout(grid);
        //Labels
        WebLabel titleLabel = new WebLabel("Cando Database Setup");
        titleLabel.setMargin(0, 125, 0, 0);
        
        //Progress Bar
        this.progressBar = new WebProgressBar ();
        this.progressBar.setIndeterminate (false);
        this.progressBar.setStringPainted (true);
        this.progressBar.setString("");
        
        //Buttons
        //Populate compound mapping table
        this.popCompMapTable = new WebButton("Populate Compound Mapping Table");
        this.popCompMapTable.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				progressBar.setIndeterminate(true);
				progressBar.setString("Populating compound mapping table...");
				popCompMapTable.setEnabled(false);
				popCandoTable.setEnabled(false);

				new CompoundMappingHandler().execute();
			}
		});  
		//Populate Cando table
        this.popCandoTable = new WebButton("Populate Cando Table");
        this.popCandoTable.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				progressBar.setIndeterminate(true);
				progressBar.setString("Populating cando table may take a few min...");
				popCandoTable.setEnabled(false);
				if (popCompMapTable.isEnabled()) {
					popCompMapTable.setEnabled(false);
				}
				new CandoTableHandler().execute();
			}
		});  
        //Create cando table button
        final WebButton candoTableButton = new WebButton("Create Cando Table");
        if (this.database.checkTableExists(this.database.getCandoTableName() + "_1")) {
        	candoTableButton.setEnabled(false);
        	candoTableButton.setText("Cando Table Already Exists");
        }
        candoTableButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final CreateCandoTable createTable = new CreateCandoTable(database);
				
				for (int i = 0; i < database.getNumVerticalPartitions(); i++) {
					database.executeScript(createTable.withPartitions(i));
					logger.info("Table partition {} creation SUCCESS.", i);
				}
				logger.info("All {} table partitions created successfully.", database.getNumVerticalPartitions());
				candoTableButton.setEnabled(false);
				candoTableButton.setText("Cando Table Created Successfully");
			}
		});  
		//Create compound mapping table button
        final WebButton compMappingButton = new WebButton("Create Compound Mapping Table");
        if (this.database.checkTableExists(this.database.getCompoundTableName())) {
        	compMappingButton.setEnabled(false);
        	compMappingButton.setText("Compound Mapping Table Already Exists");
        }
        compMappingButton.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				final CreateCompoundMappingTable compoundTable = new CreateCompoundMappingTable(database);
				database.executeScript(compoundTable.getCompoundMappingScript());
				logger.info("Compound mapping table created successfully");
				compMappingButton.setEnabled(false);
				compMappingButton.setText("Compound mapping table created successfully");
			}
		});
        
        //Alignment
        this.progressBar.setAlignmentX(CENTER_ALIGNMENT);
        compMappingButton.setAlignmentX(CENTER_ALIGNMENT);
        candoTableButton.setAlignmentX(CENTER_ALIGNMENT);
        popCandoTable.setAlignmentX(CENTER_ALIGNMENT);
        popCompMapTable.setAlignmentX(CENTER_ALIGNMENT);
        titleLabel.setAlignmentX(CENTER_ALIGNMENT);
        
        //Opacity
        masterPanel.setOpaque(false);
        
        //Final Construction
        masterPanel.add(titleLabel);
        masterPanel.add(candoTableButton);
        masterPanel.add(compMappingButton);
        masterPanel.add(popCandoTable);
        masterPanel.add(popCompMapTable);
        masterPanel.add(this.progressBar);
        
        this.add(masterPanel);
	}
	
	private class CompoundMappingHandler extends SwingWorker<String, Object> {
		long startTime;
		
		@Override
		public String doInBackground() {
			startTime = System.nanoTime();
			final CreateCompoundMappingTable compoundTable = new CreateCompoundMappingTable(database);
			try {
				compoundTable.populateCompoundMappingTable(database.getDBConnection());
			} catch (SQLException ex) {
				logger.error("SQL error populating compound mapping table: ", ex);
				database.displayErrorMessage("SQL error while populating compound mapping table. Message: " + ex.toString());
			} catch (IOException ex) {
				logger.error("IO error populating compound mapping table: ", ex);
				database.displayErrorMessage("IO error while populating compound mapping table. Message: " + ex.toString());
			}
			
			return "done";
		}

		@Override
		protected void done() {
			popCompMapTable.setEnabled(false);
			popCompMapTable.setText("Populate Compound Mapping Table Success");
			progressBar.setIndeterminate(false);
			progressBar.setString("");
			long estimatedTime = System.nanoTime() - startTime;
			int seconds = (int) (estimatedTime / 1000000000.0);
			logger.info("Populate compound mapping table SUCCESS");
			logger.info("Total time: {} minutes {} seconds\n", (seconds / 60), (seconds % 60));
			if (!popCandoTable.getText().equals("Populate Cando Table Success")) {
				popCandoTable.setEnabled(true);
			}
		}
	   }
	private class CandoTableHandler extends SwingWorker<String, Object> {
		long startTime;

		@Override
		public String doInBackground() {
			startTime = System.nanoTime();
			final PopulateCandoTable popTable = new PopulateCandoTable(database);
			try {
				popTable.populateCandoTable(database.getDBConnection());
			} catch (NumberFormatException ex) {
				logger.error("Number format error during population of cando table: {}", ex);
				database.displayErrorMessage("Number format error during population of cando table: " + ex.toString());
			} catch (IOException ex) {
				logger.error("IO error during population of cando table: {}", ex);
				database.displayErrorMessage("IO error during population of cando table: " + ex.toString());
			} catch (SQLException ex) {
				logger.error("SQL error during population of cando table: {}", ex);
				database.displayErrorMessage("SQL error during population of cando table: " + ex.toString());
			}

			return "done";
		}

		@Override
		protected void done() {
			logger.info("Populate cando table SUCCESS");
			popCandoTable.setEnabled(false);
			popCandoTable.setText("Populate Cando Table Success");
			progressBar.setIndeterminate(false);
			progressBar.setString("");
			long estimatedTime = System.nanoTime() - startTime;
			int seconds = (int) (estimatedTime / 1000000000.0);
			logger.info("Heat map data generation complete.");
			logger.info("Total time: {} minutes {} seconds\n", (seconds / 60), (seconds % 60));
			if (!popCompMapTable.getText().equals("Populate compound mapping table SUCCESS")) {
				popCompMapTable.setEnabled(true);
			}
		}
	}
}
